/* SelChooser.m
 * Written By:  Thomas Burkholder
 *
 * You may freely copy, distribute, and reuse the code in this example.
 * NeXT disclaims any warranty of any kind, expressed or  implied, as to its
 * fitness for any particular use.
 */

#import "SelChooser.h"
#import "../Utilities.subproj/SortedStorage.h"
#import "SelectorAgent.h"
#import "SelectorBrowsingFunctions.h"
#import <appkit/appkit.h>

static id selChooser;

@implementation SelChooser

+ (SEL)chooseSelectorFor:anObject numArgs:(int)num startWith:(SEL)aSel
{
	if (!selChooser)
		selChooser = [[self alloc] init];
	[selChooser setNumArgs:num];
	[selChooser setSelSource:anObject];
	[selChooser setStartWith:aSel];
	return [selChooser choose];
}

- setNumArgs:(int)num
{
	numArgs = num;
	return self;
}

- setSelSource:anObject
{
	selSource = anObject;
	return self;
}

- setStartWith:(SEL)aSel
{
	startWith = aSel;
	return self;
}

- refreshFromVars
{
	int choice;
	CAElementFilterFunc *filterFunction;

	choice = [[[popUp target] itemList] selectedRow];
	[storage empty];

	switch (numArgs) {
		case  -1 : filterFunction = NULL; break;
		case   0 : filterFunction = (choice==2)?isAccessor:hasNoArguments;
				break;
		case   1 : filterFunction = (choice==2)?isModifier:hasOneArgument;
				break;
		default  : filterFunction = NULL; break;
	}
	[selSource methodSelectors:storage includeAncestors:(choice !=1)
				filterWith:filterFunction];
	
	return self;
}

- popUpChanged:sender
{
	[self refreshFromVars];
	[browser loadColumnZero];
	return self;
}

- (SEL)choose
{
	int a, res;

	[self refreshFromVars];
	[window center];
	[window makeKeyAndOrderFront:self];
	[window makeFirstResponder:browser];
	[browser loadColumnZero];
	if (startWith) { char *str;
		str = malloc(5+strlen(sel_getName(startWith)));
		sprintf(str,"/%s",sel_getName(startWith));
		[browser setPath:str];
		free (str);
	}
	res = [NXApp runModalFor:window];
	if (res == NX_RUNABORTED) return startWith;
	if ((a = [[browser matrixInColumn:0] selectedRow]) >= 0) {
		return (SEL)(*(SEL *)[storage elementAt:a]);
	} else
		return (SEL)0;
}

- init
{
	char buf[MAXPATHLEN + 1];
	id bundle;
	[super init];
	bundle = [NXBundle bundleForClass:[self class]];
	[bundle getPath:buf forResource:"SelChooser" ofType:"nib"];
	[NXApp loadNibFile:buf owner:self withNames:NO fromZone:[self zone]];
	[browser setDoubleAction:@selector(ok:)];
	[[[popUp target] itemList] selectCellAt:0 :0];
	[[[popUp target] itemList] setTarget:self];
	[[[popUp target] itemList] setAction:@selector(popUpChanged:)];
	storage = [[SortedStorage alloc] initCount:0 elementSize:sizeof(SEL)
										description:":"];
	[storage setAgent:[[SelectorAgent alloc] init]];
	[browser setDelegate:storage];
	return self;
}

- free
{
	// Theoretically, this would leak the nib.  In practice, the chooser
	// isn't freed.
	[storage free];
	return [super free];
}

- ok:sender
{
	[NXApp stopModal];
	[window orderOut:self];
	return self;
}

- cancel:sender;
{
	[window orderOut:self];
	[NXApp abortModal];
	return self;
}

@end